﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using ChessGameV2.Pieces;
using ChessGameV2.AI.form;

namespace ChessGameV2.AI
{
    public class Thinking
    {
        #region properties
        Move _theBestMove;
        public Move test;
        public Thread process=null;
        int[] board;
        List<Move> listMove;
        public ThreadState State
        {
            get
            {
                if(process != null)
                    return process.ThreadState;
                return ThreadState.Stopped;
            }
        }
        bool ababort;
        public Move MoveAnalysis;
        int deep = 0;				//actual deep
        int target = 4;				//target deep
        
        int countbest=0;
        static frmThinking FrmThingKing = null;

        
        float value;
        float[] minimax = new float[10];
        float[] alphabeta = new float[10];	//Alpha Beta
        
        private int PlayerAnalysis;
        Evalution evalution;

        /// <summary>
        /// Di chuyen tot nhat
        /// </summary>
        public Move theBestMove
        {
            get
            {
                return _theBestMove;
            }
        }
        #endregion
        public Thinking(int[] _broad, List<Move> _listMove, int player)
        {
            listMove = _listMove;
            this.PlayerAnalysis = player;
            board = new int[120];
            for (int i = 0; i < 120; i++)
                board[i] = _broad[i];
            evalution = new Evalution();
            alphabeta[0] = int.MinValue;
            /*
            if (FrmThingKing == null)
            {
                FrmThingKing = new frmThinking(target);
                FrmThingKing.Show();
            }
            */            
        }
        /// <summary>
        /// Ham khoi tao tien trinh tim kiem
        /// </summary>
        public void execThinking()
        {
            if (process != null)    return;
            process = new Thread(findBestMove);
            process.Start();
        }
        /// <summary>
        /// Ham dung tien trinh tim kiem
        /// </summary>
        public void arbort()
        {
            if (process != null)
            {
                process.Abort();
                process = null;
            }
            
        }
        /// <summary>
        /// Ham tim kiem di chuyen tot nhat
        /// </summary>
        public void findBestMove()
        {
            /*
            if (listMove == null || listMove.Count == 0)
            {
                this._theBestMove = null;
                return;
            }
            if (listMove.Count == 1)
            {
                this._theBestMove = listMove[0];
                return;
            }*/
            search(listMove);
        }
        /// <summary>
        /// Ham duyet cac nuoc di voi tap cac nuoc di cho truoc
        /// </summary>
        /// <param name="listNextMove"></param>
        private void search(List<Move> listNextMove)
        {
            deep++;
            ababort = false;
            if (deep % 2 != 0)
            {	//computer
                minimax[deep] = float.MaxValue;
                alphabeta[deep] = float.MaxValue;
            }
            else
            {
                //human
                minimax[deep] = float.MinValue;
                alphabeta[deep] = float.MinValue;
            }
            foreach (Move movex in listNextMove)
            {
                search(movex);
            }
            deep--;
            ababort = false;
        }
        /// <summary>
        /// Ham danh gia mot nuoc di . Su dung apla-beta de quy den ham Seach(listMove)
        /// </summary>
        /// <param name="move"></param>
        private void search(Move move)
        {
            if (ababort)	//Alpha / Beta
                return;

            move.ExecuteMove(board);

            if (target == deep)
                value = evalution.Board(board, this.PlayerAnalysis);
            else
            {
                if (this.PlayerAnalysis == 1)
                    this.PlayerAnalysis = 2;
                else
                    this.PlayerAnalysis = 1;
                search(new Moves(this.PlayerAnalysis, this.board));
                value = minimax[deep + 1];
                //Alpha Beta
                if (deep % 2 != 0)
                {	//Computer
                    if (value < alphabeta[deep])
                        alphabeta[deep] = value;
                }
                else
                {
                    //human
                    if (value > alphabeta[deep])
                        alphabeta[deep] = value;
                }

                if (this.PlayerAnalysis == 1)
                    this.PlayerAnalysis = 2;
                else
                    this.PlayerAnalysis = 1;
            }

            //Minimax
            if (deep % 2 == 0)
            {	//Human
                if (value > minimax[deep])
                    minimax[deep] = value;
                //Alphabeta
                if (value > alphabeta[deep - 1])
                    ababort = true;
            }
            else
            {
                //Computer
                if (value <= minimax[deep])
                {
                    minimax[deep] = value;
                    if (deep == 1)
                    {
                        countbest++;
                        this._theBestMove = move;
                    }
                }
                //Alphabeta
                if (value < alphabeta[deep - 1])
                    ababort = true;
            }

            move.undo(board);
        }
    }
}
